package com.tanavlog.common.exception;
import com.tanavlog.common.enums.ResultCodeEnum;
import com.tanavlog.common.properties.CommonProperties;
import com.tanavlog.common.response.CommonResult;
import com.tanavlog.common.service.MailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 枫花恋
 * @description 全局异常处理器
 * @since 2025/7/24 23:32
 */
@Slf4j
@RestControllerAdvice
// 全局异常处理器，统一拦截项目中抛出的异常，避免堆栈信息直接暴露给用户
public class GlobalExceptionHandler {


    @Autowired
    private CommonProperties commonProperties;

    // 注入邮件发送服务
    @Autowired
    private MailService mailService;

    /**
     * 处理自定义业务异常（如用户余额不足、权限不足等可控性错误）
     */
    @ExceptionHandler(value = BizException.class)
    public CommonResult<?> handleBizException(BizException e, HttpServletRequest request) {
        log.warn("业务异常：[{}] -> {}", request.getRequestURI(), e.getMessage());
        return CommonResult.fail(e.getResultCodeEnum()); // 返回自定义的错误码与信息
    }

    /**
     * 处理非法参数异常（如某个接口要求参数非空却没传）
     */
    @ExceptionHandler({IllegalArgumentException.class})
    public CommonResult<?> handleIllegalArgument(BizException e, HttpServletRequest request) {
        log.warn("参数异常 [{}] - {}", request.getRequestURI(), e.getMessage());
        return CommonResult.fail(ResultCodeEnum.BAD_REQUEST); // 返回 400 错误码
    }

    /**
     * 处理非法参数异常（如某个接口要求参数非空却没传）
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public CommonResult<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
        BindingResult bindingResult = e.getBindingResult();
        List<String> msg = bindingResult.getFieldErrors().stream().map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage()).collect(Collectors.toList());
        return CommonResult.fail(msg.toString(), ResultCodeEnum.BAD_REQUEST.getCode());
    }

    /**
     * 处理常见运行时异常（如空指针、数组越界等）
     * 同时发送异常信息到指定邮箱
     */
    @ExceptionHandler(RuntimeException.class)
    public CommonResult<?> handleRuntimeException(RuntimeException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI(); // 异常来源接口路径
        log.error("运行时异常 [{}] - {}", requestURI, e.getMessage(), e);

        // 构造邮件主题与内容
        String subject = "[异常告警] 后台系统异常 - " + e.getClass().getSimpleName();
        String content = "请求路径：" + requestURI + "\n\n"
                + "异常信息：" + e.getMessage() + "\n\n"
                + "时间：" + LocalDateTime.now();

        // 异步发送邮件告警
        mailService.sendSimpleMail(commonProperties.getError().getNoticeEmail(), subject, content);
        return CommonResult.fail(ResultCodeEnum.INTERNAL_ERROR); // 返回 500 错误码
    }

    /**
     * 兜底处理所有其他异常（确保没有漏网之鱼）
     * 同样进行邮件告警
     */
    @ExceptionHandler(Exception.class)
    public CommonResult<?> handleException(Exception e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("系统异常 [{}] - {}", requestURI, e.getMessage(), e);

        String subject = "[异常告警] 后台系统异常 - " + e.getClass().getSimpleName();
        String content = "请求路径：" + requestURI + "\n\n"
                + "异常信息：" + e.getMessage() + "\n\n"
                + "时间：" + LocalDateTime.now();

        mailService.sendSimpleMail(commonProperties.getError().getNoticeEmail(), subject, content);

        return CommonResult.fail(ResultCodeEnum.UNKNOWN); // 返回通用未知错误码
    }
}

